library(peakRAM)
Warning: package ‘peakRAM’ was built under R version 4.2.3
memused<-peakRAM({
library("tidyverse")
library("e1071")
library("caret")
library("ggplot2")
library("reshape2")
library("plotly")
library("pryr")
library(randomForest)
})
── Attaching core tidyverse packages ────────────────────────────────── tidyverse 2.0.0 ──
✔ dplyr     1.1.0     ✔ readr     2.1.4
✔ forcats   1.0.0     ✔ stringr   1.5.0
✔ ggplot2   3.4.1     ✔ tibble    3.1.8
✔ lubridate 1.9.2     ✔ tidyr     1.3.0
✔ purrr     1.0.1     ── Conflicts ──────────────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
ℹ Use the ]8;;http://conflicted.r-lib.org/conflicted package]8;; to force all conflicts to become errorsWarning: package ‘e1071’ was built under R version 4.2.3Warning: package ‘caret’ was built under R version 4.2.3Loading required package: lattice
Registered S3 method overwritten by 'data.table':
  method           from
  print.data.table     

Attaching package: ‘caret’

The following object is masked from ‘package:purrr’:

    lift

Warning: package ‘reshape2’ was built under R version 4.2.3
Attaching package: ‘reshape2’

The following object is masked from ‘package:tidyr’:

    smiths

Warning: package ‘plotly’ was built under R version 4.2.3Registered S3 method overwritten by 'htmlwidgets':
  method           from         
  print.htmlwidget tools:rstudio

Attaching package: ‘plotly’

The following object is masked from ‘package:ggplot2’:

    last_plot

The following object is masked from ‘package:stats’:

    filter

The following object is masked from ‘package:graphics’:

    layout

Warning: package ‘pryr’ was built under R version 4.2.3
Attaching package: ‘pryr’

The following object is masked from ‘package:dplyr’:

    where

The following objects are masked from ‘package:purrr’:

    compose, partial

Warning: package ‘randomForest’ was built under R version 4.2.3randomForest 4.7-1.1
Type rfNews() to see new features/changes/bug fixes.

Attaching package: ‘randomForest’

The following object is masked from ‘package:dplyr’:

    combine

The following object is masked from ‘package:ggplot2’:

    margin
cat("CPU time usage of code chunk:",memused$Elapsed_Time_sec,"\n")
CPU time usage of code chunk: 2.58 
cat("Memory usage of code chunk:",memused$Peak_RAM_Used_MiB, "MiB\n")
Memory usage of code chunk: 43 MiB
memused<-peakRAM({
car<-read.csv("../ca-dealers-used.csv")
})
cat("CPU time usage of code chunk:",memused$Elapsed_Time_sec,"\n")
CPU time usage of code chunk: 4.54 
cat("Memory usage of code chunk:",memused$Peak_RAM_Used_MiB, "MiB\n")
Memory usage of code chunk: 172.4 MiB
# DATA PREPROCESSING
# 1. FEATURE SELECTION
# 2. REMOVING MISSING AND NAN VALUES
# 3. CONVERTING COLUMNS WITH STRING VALUES INTO CATEGORICAL NUMERIC VALUES

memused<-peakRAM({

car<-subset(car,select=c(miles, year, make, model,trim,body_type, vehicle_type, drivetrain, transmission, fuel_type,engine_size, city,price))
car_viz<-car
clean_dataset <- function(df) {
  stopifnot(is.data.frame(df))
  df <- na.omit(df) # Drop missing values
  indices_to_keep <- !apply(df, 1, function(row) any(is.na(row) | is.infinite(row) | row == -Inf)) # Check for NaN, Inf, and -Inf
  df <- df[indices_to_keep, , drop = FALSE]
  df <- as.data.frame(lapply(df, as.numeric)) # Convert the remaining columns to numeric type
  return(df)
}

for (col in names(car)) {
  # Check if the column is not a character type
  if (is.character(car[[col]])) {
    # Convert the column to a factor
    car[[col]] <- as.numeric(factor(car[[col]]))
  }
}

car_training<-car[,1:13]

car_training2<-clean_dataset(car_training) 

})
cat("CPU time usage of code chunk:",memused$Elapsed_Time_sec,"\n")
CPU time usage of code chunk: 1.76 
cat("Memory usage of code chunk:",memused$Peak_RAM_Used_MiB, "MiB\n")
Memory usage of code chunk: 150.3 MiB
write.csv(car_training2, file = "my_data.csv")
#BASIC EDA

hist(car_viz$price,breaks=1000,main="Price",xlab = "Price range",ylab="Count")

hist(car_viz$miles,main="Price",xlab = "Price range",ylab="Count")

#vizualizing the data for make and count of body type
start_time <- Sys.time()
mem_start <- mem_used()

ggplot(car_viz, aes(x = make)) +
  geom_bar(aes(fill = body_type)) +
  labs(x = "Make", y = "Count of Body Type", title = "Make vs Body Type") +
  theme(plot.title = element_text(size = 18),axis.text.x = element_text(angle = 65,  hjust = 1),legend.key.size = unit(0.2,'cm'),legend.text = element_text(size = 5), legend.title = element_text(size = 5),
        legend.box = "vertical")


end_time <- Sys.time()
mem_end <- mem_used()
cpu_time <- end_time - start_time
mem_used_chunk <- mem_end - mem_start
cat("CPU time usage of code chunk:",cpu_time,"\n")
CPU time usage of code chunk: 1.617222 
cat("Memory usage of code chunk:", mem_used_chunk/1000000, "MiB\n")
Memory usage of code chunk: 15.14197 MiB
start_time <- Sys.time()
mem_start <- mem_used()

plotinter<-ggplot(car_viz, aes(x = make)) +
  geom_bar(aes(fill = body_type)) +
  labs(x = "Make", y = "Count of Body Type", title = "Make vs Body Type") +
  theme(plot.title = element_text(size = 18),axis.text.x = element_text(angle = 65,  hjust = 1),legend.key.size = unit(0.2,'cm'),legend.text = element_text(size = 5), legend.title = element_text(size = 5),
        legend.box = "vertical")
ggplotly(plotinter)

end_time <- Sys.time()
mem_end <- mem_used()
cpu_time <- end_time - start_time
mem_used_chunk <- mem_end - mem_start
cat("CPU time usage of code chunk:",cpu_time,"\n")
CPU time usage of code chunk: 1.542377 
cat("Memory usage of code chunk:", mem_used_chunk/1048576, "MB\n")
Memory usage of code chunk: 18.65584 MB
#ML model TEST TRAIN SPLIT


memused<-peakRAM({
X<-car_training2[,1:12]
Y<-car_training2[,13]
set.seed(42)
splitIndex <- createDataPartition(Y, p = 0.7, list = FALSE, times = 1)
x_train <- X[splitIndex, ]
x_test <- X[-splitIndex, ]
y_train <- Y[splitIndex]
y_test <- Y[-splitIndex]

})
cat("CPU time usage of code chunk:",memused$Elapsed_Time_sec,"\n")
CPU time usage of code chunk: 0.16 
cat("Memory usage of code chunk:",memused$Peak_RAM_Used_MiB, "MiB\n")
Memory usage of code chunk: 114.1 MiB
#ML Linear Regression Training and testing

memused<-peakRAM({

lm_model <- train(x_train, y_train, method = "lm")
y_pred <- predict(lm_model, x_test)

})
cat("CPU time usage of code chunk:",memused$Elapsed_Time_sec,"\n")
CPU time usage of code chunk: 23.48 
cat("Memory usage of code chunk:",memused$Peak_RAM_Used_MiB, "MiB\n")
Memory usage of code chunk: 421.4 MiB
#Calculating metrics
mse <- mean((y_pred - y_test)^2)
mae <- mean(abs(y_pred - y_test))
rmse <- sqrt(mse)

cat("Linear Regression MSE: ", mse,"\n")
Linear Regression MSE:  216112618 
cat("Linear Regression MAE: ", mae,"\n")
Linear Regression MAE:  7118.532 
cat("Linear Regression RMSE: ", rmse,"\n")
Linear Regression RMSE:  14700.77 
object.size(lm_model)
143024064 bytes
# KNN Model
memused<-peakRAM({

knnmodel = knnreg(x_train, y_train)
y_pred <- predict(knnmodel,x_test)

})
cat("CPU time usage of code chunk:",memused$Elapsed_Time_sec,"\n")
CPU time usage of code chunk: 125.82 
cat("Memory usage of code chunk:",memused$Peak_RAM_Used_MiB, "MiB\n")
Memory usage of code chunk: 98.1 MiB
#Calculating metrics
mse <- mean((y_pred - y_test)^2)
mae <- mean(abs(y_pred - y_test))
rmse <- sqrt(mse)

cat("KNN MSE: ", mse,"\n")
KNN MSE:  279466774 
cat("KNN MAE: ", mae,"\n")
KNN MAE:  9075.661 
cat("KNN RMSE: ", rmse,"\n")
KNN RMSE:  16717.26 
#Random Forest

memused<-peakRAM({

#rf_model <- train(x_train, y_train,method="rf")# Use the model to predict on X_test
#y_pred <- predict(rf_model, x_test)# Evaluate the model performance


rf_model = randomForest(x = x_train,
                             y = y_train,ntree=50)
  
# Predicting the Test set results
y_pred = predict(rf_model, newdata = x_test)

})
cat("CPU time usage of code chunk:",memused$Elapsed_Time_sec,"\n")
cat("Memory usage of code chunk:",memused$Peak_RAM_Used_MiB, "MiB\n")

#Calculating metrics
mse <- mean((y_pred - y_test)^2)
mae <- mean(abs(y_pred - y_test))
rmse <- sqrt(mse)

cat("Random Forest MSE: ", mse,"\n")
cat("Random Forest MAE: ", mae,"\n")
cat("Random Forest RMSE: ", rmse,"\n")
LS0tDQp0aXRsZTogIlIgTm90ZWJvb2sgdHJhaW5pbmcgTUwgbW9kZWxzIGFuZCBjYWxjdWxhdGluZyBlZmZpY2llbmNpZXMgaW4gUiINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQoNCmBgYHtyfQ0KbGlicmFyeShwZWFrUkFNKQ0KbWVtdXNlZDwtcGVha1JBTSh7DQpsaWJyYXJ5KCJ0aWR5dmVyc2UiKQ0KbGlicmFyeSgiZTEwNzEiKQ0KbGlicmFyeSgiY2FyZXQiKQ0KbGlicmFyeSgiZ2dwbG90MiIpDQpsaWJyYXJ5KCJyZXNoYXBlMiIpDQpsaWJyYXJ5KCJwbG90bHkiKQ0KbGlicmFyeSgicHJ5ciIpDQpsaWJyYXJ5KHJhbmRvbUZvcmVzdCkNCn0pDQpjYXQoIkNQVSB0aW1lIHVzYWdlIG9mIGNvZGUgY2h1bms6IixtZW11c2VkJEVsYXBzZWRfVGltZV9zZWMsIlxuIikNCmNhdCgiTWVtb3J5IHVzYWdlIG9mIGNvZGUgY2h1bms6IixtZW11c2VkJFBlYWtfUkFNX1VzZWRfTWlCLCAiTWlCXG4iKQ0KYGBgDQoNCg0KYGBge3J9DQptZW11c2VkPC1wZWFrUkFNKHsNCmNhcjwtcmVhZC5jc3YoIi4uL2NhLWRlYWxlcnMtdXNlZC5jc3YiKQ0KfSkNCmNhdCgiQ1BVIHRpbWUgdXNhZ2Ugb2YgY29kZSBjaHVuazoiLG1lbXVzZWQkRWxhcHNlZF9UaW1lX3NlYywiXG4iKQ0KY2F0KCJNZW1vcnkgdXNhZ2Ugb2YgY29kZSBjaHVuazoiLG1lbXVzZWQkUGVha19SQU1fVXNlZF9NaUIsICJNaUJcbiIpDQoNCmBgYA0KDQoNCmBgYHtyfQ0KIyBEQVRBIFBSRVBST0NFU1NJTkcNCiMgMS4gRkVBVFVSRSBTRUxFQ1RJT04NCiMgMi4gUkVNT1ZJTkcgTUlTU0lORyBBTkQgTkFOIFZBTFVFUw0KIyAzLiBDT05WRVJUSU5HIENPTFVNTlMgV0lUSCBTVFJJTkcgVkFMVUVTIElOVE8gQ0FURUdPUklDQUwgTlVNRVJJQyBWQUxVRVMNCg0KbWVtdXNlZDwtcGVha1JBTSh7DQoNCmNhcjwtc3Vic2V0KGNhcixzZWxlY3Q9YyhtaWxlcywgeWVhciwgbWFrZSwgbW9kZWwsdHJpbSxib2R5X3R5cGUsIHZlaGljbGVfdHlwZSwgZHJpdmV0cmFpbiwgdHJhbnNtaXNzaW9uLCBmdWVsX3R5cGUsZW5naW5lX3NpemUsIGNpdHkscHJpY2UpKQ0KY2FyX3ZpejwtY2FyDQpjbGVhbl9kYXRhc2V0IDwtIGZ1bmN0aW9uKGRmKSB7DQogIHN0b3BpZm5vdChpcy5kYXRhLmZyYW1lKGRmKSkNCiAgZGYgPC0gbmEub21pdChkZikgIyBEcm9wIG1pc3NpbmcgdmFsdWVzDQogIGluZGljZXNfdG9fa2VlcCA8LSAhYXBwbHkoZGYsIDEsIGZ1bmN0aW9uKHJvdykgYW55KGlzLm5hKHJvdykgfCBpcy5pbmZpbml0ZShyb3cpIHwgcm93ID09IC1JbmYpKSAjIENoZWNrIGZvciBOYU4sIEluZiwgYW5kIC1JbmYNCiAgZGYgPC0gZGZbaW5kaWNlc190b19rZWVwLCAsIGRyb3AgPSBGQUxTRV0NCiAgZGYgPC0gYXMuZGF0YS5mcmFtZShsYXBwbHkoZGYsIGFzLm51bWVyaWMpKSAjIENvbnZlcnQgdGhlIHJlbWFpbmluZyBjb2x1bW5zIHRvIG51bWVyaWMgdHlwZQ0KICByZXR1cm4oZGYpDQp9DQoNCmZvciAoY29sIGluIG5hbWVzKGNhcikpIHsNCiAgIyBDaGVjayBpZiB0aGUgY29sdW1uIGlzIG5vdCBhIGNoYXJhY3RlciB0eXBlDQogIGlmIChpcy5jaGFyYWN0ZXIoY2FyW1tjb2xdXSkpIHsNCiAgICAjIENvbnZlcnQgdGhlIGNvbHVtbiB0byBhIGZhY3Rvcg0KICAgIGNhcltbY29sXV0gPC0gYXMubnVtZXJpYyhmYWN0b3IoY2FyW1tjb2xdXSkpDQogIH0NCn0NCg0KY2FyX3RyYWluaW5nPC1jYXJbLDE6MTNdDQoNCmNhcl90cmFpbmluZzI8LWNsZWFuX2RhdGFzZXQoY2FyX3RyYWluaW5nKSANCg0KfSkNCmNhdCgiQ1BVIHRpbWUgdXNhZ2Ugb2YgY29kZSBjaHVuazoiLG1lbXVzZWQkRWxhcHNlZF9UaW1lX3NlYywiXG4iKQ0KY2F0KCJNZW1vcnkgdXNhZ2Ugb2YgY29kZSBjaHVuazoiLG1lbXVzZWQkUGVha19SQU1fVXNlZF9NaUIsICJNaUJcbiIpDQoNCndyaXRlLmNzdihjYXJfdHJhaW5pbmcyLCBmaWxlID0gIm15X2RhdGEuY3N2IikNCmBgYA0KYGBge3J9DQojQkFTSUMgRURBDQoNCmhpc3QoY2FyX3ZpeiRwcmljZSxicmVha3M9MTAwMCxtYWluPSJQcmljZSIseGxhYiA9ICJQcmljZSByYW5nZSIseWxhYj0iQ291bnQiKQ0KaGlzdChjYXJfdml6JG1pbGVzLG1haW49IlByaWNlIix4bGFiID0gIlByaWNlIHJhbmdlIix5bGFiPSJDb3VudCIpDQpgYGANCg0KDQpgYGB7cn0NCiN2aXp1YWxpemluZyB0aGUgZGF0YSBmb3IgbWFrZSBhbmQgY291bnQgb2YgYm9keSB0eXBlDQpzdGFydF90aW1lIDwtIFN5cy50aW1lKCkNCm1lbV9zdGFydCA8LSBtZW1fdXNlZCgpDQoNCmdncGxvdChjYXJfdml6LCBhZXMoeCA9IG1ha2UpKSArDQogIGdlb21fYmFyKGFlcyhmaWxsID0gYm9keV90eXBlKSkgKw0KICBsYWJzKHggPSAiTWFrZSIsIHkgPSAiQ291bnQgb2YgQm9keSBUeXBlIiwgdGl0bGUgPSAiTWFrZSB2cyBCb2R5IFR5cGUiKSArDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE4KSxheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDY1LCAgaGp1c3QgPSAxKSxsZWdlbmQua2V5LnNpemUgPSB1bml0KDAuMiwnY20nKSxsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gNSksIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gNSksDQogICAgICAgIGxlZ2VuZC5ib3ggPSAidmVydGljYWwiKQ0KDQplbmRfdGltZSA8LSBTeXMudGltZSgpDQptZW1fZW5kIDwtIG1lbV91c2VkKCkNCmNwdV90aW1lIDwtIGVuZF90aW1lIC0gc3RhcnRfdGltZQ0KbWVtX3VzZWRfY2h1bmsgPC0gbWVtX2VuZCAtIG1lbV9zdGFydA0KY2F0KCJDUFUgdGltZSB1c2FnZSBvZiBjb2RlIGNodW5rOiIsY3B1X3RpbWUsIlxuIikNCmNhdCgiTWVtb3J5IHVzYWdlIG9mIGNvZGUgY2h1bms6IiwgbWVtX3VzZWRfY2h1bmsvMTAwMDAwMCwgIk1pQlxuIikNCg0KYGBgDQoNCmBgYHtyfQ0Kc3RhcnRfdGltZSA8LSBTeXMudGltZSgpDQptZW1fc3RhcnQgPC0gbWVtX3VzZWQoKQ0KDQpwbG90aW50ZXI8LWdncGxvdChjYXJfdml6LCBhZXMoeCA9IG1ha2UpKSArDQogIGdlb21fYmFyKGFlcyhmaWxsID0gYm9keV90eXBlKSkgKw0KICBsYWJzKHggPSAiTWFrZSIsIHkgPSAiQ291bnQgb2YgQm9keSBUeXBlIiwgdGl0bGUgPSAiTWFrZSB2cyBCb2R5IFR5cGUiKSArDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE4KSxheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDY1LCAgaGp1c3QgPSAxKSxsZWdlbmQua2V5LnNpemUgPSB1bml0KDAuMiwnY20nKSxsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gNSksIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gNSksDQogICAgICAgIGxlZ2VuZC5ib3ggPSAidmVydGljYWwiKQ0KZ2dwbG90bHkocGxvdGludGVyKQ0KDQplbmRfdGltZSA8LSBTeXMudGltZSgpDQptZW1fZW5kIDwtIG1lbV91c2VkKCkNCmNwdV90aW1lIDwtIGVuZF90aW1lIC0gc3RhcnRfdGltZQ0KbWVtX3VzZWRfY2h1bmsgPC0gbWVtX2VuZCAtIG1lbV9zdGFydA0KY2F0KCJDUFUgdGltZSB1c2FnZSBvZiBjb2RlIGNodW5rOiIsY3B1X3RpbWUsIlxuIikNCmNhdCgiTWVtb3J5IHVzYWdlIG9mIGNvZGUgY2h1bms6IiwgbWVtX3VzZWRfY2h1bmsvMTA0ODU3NiwgIk1CXG4iKQ0KYGBgDQoNCg0KDQpgYGB7cn0NCiNNTCBtb2RlbCBURVNUIFRSQUlOIFNQTElUDQoNCg0KbWVtdXNlZDwtcGVha1JBTSh7DQpYPC1jYXJfdHJhaW5pbmcyWywxOjEyXQ0KWTwtY2FyX3RyYWluaW5nMlssMTNdDQpzZXQuc2VlZCg0MikNCnNwbGl0SW5kZXggPC0gY3JlYXRlRGF0YVBhcnRpdGlvbihZLCBwID0gMC43LCBsaXN0ID0gRkFMU0UsIHRpbWVzID0gMSkNCnhfdHJhaW4gPC0gWFtzcGxpdEluZGV4LCBdDQp4X3Rlc3QgPC0gWFstc3BsaXRJbmRleCwgXQ0KeV90cmFpbiA8LSBZW3NwbGl0SW5kZXhdDQp5X3Rlc3QgPC0gWVstc3BsaXRJbmRleF0NCg0KfSkNCmNhdCgiQ1BVIHRpbWUgdXNhZ2Ugb2YgY29kZSBjaHVuazoiLG1lbXVzZWQkRWxhcHNlZF9UaW1lX3NlYywiXG4iKQ0KY2F0KCJNZW1vcnkgdXNhZ2Ugb2YgY29kZSBjaHVuazoiLG1lbXVzZWQkUGVha19SQU1fVXNlZF9NaUIsICJNaUJcbiIpDQoNCg0KYGBgDQoNCg0KDQpgYGB7cn0NCiNNTCBMaW5lYXIgUmVncmVzc2lvbiBUcmFpbmluZyBhbmQgdGVzdGluZw0KDQptZW11c2VkPC1wZWFrUkFNKHsNCg0KbG1fbW9kZWwgPC0gdHJhaW4oeF90cmFpbiwgeV90cmFpbiwgbWV0aG9kID0gImxtIikNCnlfcHJlZCA8LSBwcmVkaWN0KGxtX21vZGVsLCB4X3Rlc3QpDQoNCn0pDQpjYXQoIkNQVSB0aW1lIHVzYWdlIG9mIGNvZGUgY2h1bms6IixtZW11c2VkJEVsYXBzZWRfVGltZV9zZWMsIlxuIikNCmNhdCgiTWVtb3J5IHVzYWdlIG9mIGNvZGUgY2h1bms6IixtZW11c2VkJFBlYWtfUkFNX1VzZWRfTWlCLCAiTWlCXG4iKQ0KDQojQ2FsY3VsYXRpbmcgbWV0cmljcw0KbXNlIDwtIG1lYW4oKHlfcHJlZCAtIHlfdGVzdCleMikNCm1hZSA8LSBtZWFuKGFicyh5X3ByZWQgLSB5X3Rlc3QpKQ0Kcm1zZSA8LSBzcXJ0KG1zZSkNCg0KY2F0KCJMaW5lYXIgUmVncmVzc2lvbiBNU0U6ICIsIG1zZSwiXG4iKQ0KY2F0KCJMaW5lYXIgUmVncmVzc2lvbiBNQUU6ICIsIG1hZSwiXG4iKQ0KY2F0KCJMaW5lYXIgUmVncmVzc2lvbiBSTVNFOiAiLCBybXNlLCJcbiIpDQoNCmBgYA0KDQpgYGB7cn0NCiNzYXZlIHRoZSBtb2RlbCBhbmQgYWxzbyBjaGVjayB0aGUgc2l6ZSBvZiB0aGUgc3RvcmVkIG1vZGVsDQpzYXZlUkRTKGxtX21vZGVsLCAiTGluZWFyUmVnLnJkcyIpDQpmaWxlX2luZm8gPC0gZmlsZS5pbmZvKCJMaW5lYXJSZWcucmRzIikNCmZpbGVfc2l6ZSA8LSBmaWxlX2luZm8kc2l6ZQ0KcHJpbnQoZmlsZV9zaXplKQ0KDQpgYGANCg0KYGBge3J9DQojIEtOTiBNb2RlbA0KbWVtdXNlZDwtcGVha1JBTSh7DQoNCmtubm1vZGVsID0ga25ucmVnKHhfdHJhaW4sIHlfdHJhaW4pDQp5X3ByZWQgPC0gcHJlZGljdChrbm5tb2RlbCx4X3Rlc3QpDQoNCn0pDQpjYXQoIkNQVSB0aW1lIHVzYWdlIG9mIGNvZGUgY2h1bms6IixtZW11c2VkJEVsYXBzZWRfVGltZV9zZWMsIlxuIikNCmNhdCgiTWVtb3J5IHVzYWdlIG9mIGNvZGUgY2h1bms6IixtZW11c2VkJFBlYWtfUkFNX1VzZWRfTWlCLCAiTWlCXG4iKQ0KDQojQ2FsY3VsYXRpbmcgbWV0cmljcw0KbXNlIDwtIG1lYW4oKHlfcHJlZCAtIHlfdGVzdCleMikNCm1hZSA8LSBtZWFuKGFicyh5X3ByZWQgLSB5X3Rlc3QpKQ0Kcm1zZSA8LSBzcXJ0KG1zZSkNCg0KY2F0KCJLTk4gTVNFOiAiLCBtc2UsIlxuIikNCmNhdCgiS05OIE1BRTogIiwgbWFlLCJcbiIpDQpjYXQoIktOTiBSTVNFOiAiLCBybXNlLCJcbiIpDQoNCmBgYA0KDQoNCmBgYHtyfQ0KI1JhbmRvbSBGb3Jlc3QNCg0KbWVtdXNlZDwtcGVha1JBTSh7DQoNCiNyZl9tb2RlbCA8LSB0cmFpbih4X3RyYWluLCB5X3RyYWluLG1ldGhvZD0icmYiKSMgVXNlIHRoZSBtb2RlbCB0byBwcmVkaWN0IG9uIFhfdGVzdA0KI3lfcHJlZCA8LSBwcmVkaWN0KHJmX21vZGVsLCB4X3Rlc3QpIyBFdmFsdWF0ZSB0aGUgbW9kZWwgcGVyZm9ybWFuY2UNCg0KDQpyZl9tb2RlbCA9IHJhbmRvbUZvcmVzdCh4ID0geF90cmFpbiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeSA9IHlfdHJhaW4sbnRyZWU9NTApDQogIA0KIyBQcmVkaWN0aW5nIHRoZSBUZXN0IHNldCByZXN1bHRzDQp5X3ByZWQgPSBwcmVkaWN0KHJmX21vZGVsLCBuZXdkYXRhID0geF90ZXN0KQ0KDQp9KQ0KY2F0KCJDUFUgdGltZSB1c2FnZSBvZiBjb2RlIGNodW5rOiIsbWVtdXNlZCRFbGFwc2VkX1RpbWVfc2VjLCJcbiIpDQpjYXQoIk1lbW9yeSB1c2FnZSBvZiBjb2RlIGNodW5rOiIsbWVtdXNlZCRQZWFrX1JBTV9Vc2VkX01pQiwgIk1pQlxuIikNCg0KI0NhbGN1bGF0aW5nIG1ldHJpY3MNCm1zZSA8LSBtZWFuKCh5X3ByZWQgLSB5X3Rlc3QpXjIpDQptYWUgPC0gbWVhbihhYnMoeV9wcmVkIC0geV90ZXN0KSkNCnJtc2UgPC0gc3FydChtc2UpDQoNCmNhdCgiUmFuZG9tIEZvcmVzdCBNU0U6ICIsIG1zZSwiXG4iKQ0KY2F0KCJSYW5kb20gRm9yZXN0IE1BRTogIiwgbWFlLCJcbiIpDQpjYXQoIlJhbmRvbSBGb3Jlc3QgUk1TRTogIiwgcm1zZSwiXG4iKQ0KYGBg